home *** CD-ROM | disk | FTP | other *** search
- /* C K I U T L -- July 17, 1986
- * Utility functions for C-Kermit on the Amiga
- */
-
- /*
- Author: Jack Rouse
- Contributed to Columbia University for inclusion in C-Kermit.
- Copyright (C) 1986, Jack J. Rouse, 106 Rubin Ct. Apt. A-4, Cary NC 27511
- Permission is granted to any individual or institution to use, copy, or
- redistribute this software so long as it is not sold for profit, provided this
- copyright notice is retained.
-
- The file status routines assume all file protection modes are real, instead
- of just delete protection on files and write protection on disks.
- */
-
- #include <stdio.h>
- #undef NULL
- #include "exec/types.h"
- #include "exec/exec.h"
- #include "libraries/dos.h"
- #include "libraries/dosextens.h"
- #define fh_Interact fh_Port
- #define fh_Process fh_Type
- #define ACTION_CLOSE 1007
- #ifdef LAT304
- #include "lattice/fcntl.h"
- #include "lattice/signal.h"
- #else
- #include "lattice/ios1.h" /* defines ufbs structure */
- #endif
-
- /* external routine definitions */
- APTR AllocMem();
- LONG AllocSignal();
- struct IORequest *CheckIO();
- VOID CloseDevice();
- VOID CloseLibrary();
- LONG DoIO();
- struct MsgPort *FindPort();
- struct Task *FindTask();
- VOID FreeMem();
- VOID FreeSignal();
- struct Message *GetMsg();
- LONG OpenDevice();
- struct Library *OpenLibrary();
- VOID PutMsg();
- VOID ReplyMsg();
- VOID SendIO();
- LONG SetSignal();
- VOID Signal();
- LONG Wait();
- LONG WaitIO();
- struct Message *WaitPort();
-
- struct IORequest *CreateExtIO();
- struct MsgPort *CreatePort();
-
- VOID Close();
- LONG DeleteFile();
- LONG Execute();
- BPTR Input(), Output();
- LONG IoErr();
- LONG IsInteractive();
- BPTR Lock();
- BPTR Open();
- LONG Read();
- VOID UnLock();
- LONG WaitForChar();
-
- /* portable library */
- char *malloc();
-
- #ifdef LAT304
- /* translate Unix file handle (0, 1, or 2) to AmigaDOS file handle */
- #define DOSFH(n) fileno(&_iob[n])
- /* translate Unix file handle (0, 1, or 2) to Lattice file handle */
- #define FILENO(n) fileno(&_iob[n])
- #else
- /* Lattice runtime externals */
- extern struct UFB _ufbs[];
- extern int Enable_Abort;
- #define DOSFH(n) (_ufbs[n].ufbfh)
- #define FILENO(n) (n)
- #endif
-
- /* Amiga Kermit externals (defined in ckitio.c) */
- extern struct Process *CurProc;
- extern struct CommandLineInterface *CurCLI;
-
- /*
- * CreatePacket -- allocate and set up a AmigaDOS packet
- */
- struct DosPacket *CreatePacket()
- {
- register struct StandardPacket *sp;
-
- sp = (struct StandardPacket *)
- AllocMem((LONG)sizeof(struct StandardPacket),
- (LONG)MEMF_PUBLIC|MEMF_CLEAR);
- if (sp == NULL) return(NULL);
- sp->sp_Pkt.dp_Link = &sp->sp_Msg;
- sp->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
- sp->sp_Msg.mn_Node.ln_Name = (char *)&sp->sp_Pkt;
- sp->sp_Msg.mn_Length = sizeof(struct DosPacket);
- return(&sp->sp_Pkt);
- }
-
- /*
- * DeletePacket -- deallocate packet from CreatePacket()
- */
- VOID DeletePacket(pkt)
- struct DosPacket *pkt;
- {
- FreeMem(pkt->dp_Link, (LONG)sizeof(struct StandardPacket));
- }
-
- /*
- * system(cmd) -- execute a command
- * provides no sensible return value
- */
- system(cmd)
- char *cmd;
- {
- BPTR fh;
-
- fflush(stdout);
- if (cmd == NULL || *cmd == '\0')
- {
- fh = Open("CON:0/0/640/200/Kermit CLI", (LONG)MODE_NEWFILE);
- if (fh)
- {
- Execute("", fh, (BPTR)NULL);
-
- /* fix 'endcli' bug */
- ((struct FileHandle *)BADDR(fh))->fh_Pos = 0;
-
- Close(fh);
- }
- }
- else
- Execute(cmd, (BPTR)NULL, DOSFH(1));
- }
-
- #ifndef LAT304
- /*
- * getcwd -- get current working directory text
- */
- char *getcwd(buf, len)
- register char *buf;
- int len;
- {
- register UBYTE *dirname;
-
- if (CurCLI == NULL) return(NULL);
- dirname = (UBYTE *)BADDR(CurCLI->cli_SetName);
- if (len < *dirname + 1) return(NULL);
- strncpy(buf, dirname + 1, *dirname);
- buf[*dirname] = 0;
- return(buf);
- }
-
- /*
- * update the current directory name in the CLI process structure
- *
- * This version generates the new name from the current name and
- * the specified path, something like the CD command does.
- * A much better version could be written using Parent(), Examine(),
- * and VolInfo to reconstitute a name from a lock, but Parent() doesn't
- * work with RAM: in V1.1. The current implementation, like the CD
- * command, has difficulty with backing up the directory tree. For example
- * { chdir("c:"); chdir("/"); } results in a dir name of "c:/". However,
- * this version shouldn't get as far out of sync as the CD command. (The
- * same sequence with the CD command puts you in the parent dir of "c:" but
- * with a directory name of "c:".)
- */
- static void update_dirname(name)
- register char *name;
- {
- register UBYTE *dirname; /* DOS directory name BSTR */
- char buf[100]; /* about same size as DOS */
- register char *tail;
-
- /* locate the DOS copy of the directory name */
- if (CurCLI == NULL) return;
- dirname = (UBYTE *)BADDR(CurCLI->cli_SetName);
-
- /* if the name is anchored (like "DF1:") simply replace the name */
- if (strrchr(name, ':') != NULL)
- {
- *dirname = strlen(name);
- strncpy(&dirname[1], name, *dirname);
- return;
- }
-
- /* name is relative to current directory, copy name to work with */
- strncpy(buf, &dirname[1], *dirname);
- tail = &buf[*dirname];
-
- /* traverse the path in the name */
- while (*name)
- {
- /* go to parent dir? */
- if (*name == '/')
- { /* remove a component from the directory path */
-
- /* advance past parent slash */
- ++name;
-
- /* if at colon, can't back up */
- if (tail[-1] == ':')
- {
- *tail++ = '/';
- continue;
- }
-
- /* if at slash, see if name given */
- if (tail[-1] == '/')
- {
- /* if no name, can't back up */
- if (tail[-2] == '/' || tail[-2] == ':')
- {
- *tail++ = '/';
- continue;
- }
-
- /* remove trailing slash */
- --tail;
- }
-
- /* remove remainder of component */
- while (tail[-1] != '/' && tail[-1] != ':')
- --tail;
- }
- else
- { /* add component to directory path */
- /* add slash if necessary to separate name */
- if (tail[-1] != ':' && tail[-1] != '/')
- *tail++ = '/';
-
- /* add component name */
- while (*name && *name != '/')
- *tail++ = *name++;
-
- /* add trailing slash if specified */
- if (*name == '/')
- *tail++ = *name++;
- }
- }
-
- /* set BSTR to derived name */
- *dirname = tail - buf;
- strncpy(&dirname[1], buf, *dirname);
- }
-
- /*
- * change current directory
- */
- int chdir(name)
- char *name;
- {
- BPTR lock;
- BPTR oldlock;
- struct FileInfoBlock *fib;
-
- /* ignore chdir("") */
- if (*name == 0) return(0);
-
- /* try to look at the object */
- lock = Lock(name, (LONG)ACCESS_READ);
- if (lock == NULL) return(-1);
-
- /* make sure the file is a directory */
- fib = (struct FileInfoBlock *)malloc(sizeof(*fib));
- if (fib == NULL || !Examine(lock, fib) || fib->fib_DirEntryType <= 0)
- {
- if (fib) free(fib);
- UnLock(lock);
- return(-1);
- }
-
- /* don't need file info any more */
- free(fib);
-
- /* change the current directory */
- oldlock = CurrentDir(lock);
-
- /* update the DOS copy of the directory name */
- update_dirname(name);
-
- /* unlock the previous current directory */
- if (oldlock) UnLock(oldlock);
-
- return(0);
- }
-
- /*
- * print an error message with explanation
- * (no explanation currently)
- */
- int perror(str)
- char *str;
- {
- extern int errno;
- LONG oserr = IoErr();
-
- printf("%s: errno=%d, oserr=%ld\n", str, errno, oserr);
- }
- #endif
-
- /*
- * isatty(fd) -- determine if given file is a (virtual) terminal
- * only works for fd=0, 1, or 2 (stdin, stdout, and stderr resp.)
- */
- int isatty(fd)
- int fd;
- {
- return(IsInteractive(DOSFH(fd)) != 0);
- }
-
- /*
- * readstat -- determine file's read status
- * returns -3 if file read protected
- * returns -2 if file is a directory
- * returns -1 if file doesn't exist
- * returns file size otherwise
- */
- long readstat(name)
- char *name;
- {
- BPTR lock;
- struct FileInfoBlock *fib;
- long size;
-
- /* locate the file */
- if ((lock = Lock(name, (LONG)ACCESS_READ)) == NULL) return(-1);
-
- /* allocate a file info block */
- if ((fib = (struct FileInfoBlock *)malloc(sizeof(*fib))) == NULL)
- { size = -1; goto exit; }
-
- /* make sure it's not a directory */
- if (!Examine(lock, fib) || fib->fib_DirEntryType >= 0)
- { size = -2; goto exit; }
-
- /* make sure it's readable */
- if (fib->fib_Protection & FIBF_READ)
- { size = -3; goto exit; }
-
- size = fib->fib_Size;
- exit:
- if (fib) free(fib);
- UnLock(lock);
- return(size);
- }
-
- /*
- * writestat -- determines file's write status
- * returns 0 if file should be writable, -1 otherwise
- *
- * The following logic is used to determine if a file is writable:
- * 1. If the file exists, it must not be write or delete protected.
- * (Delete protection subsumes write protection for overwriting.)
- * 2. The parent directory must not be write protected ???
- * 3. The volume that the parent directory resides on must be
- * validated and not write protected.
- */
- int writestat(name)
- register char *name;
- {
- register char *p;
- char *lastslash;
- char path[100];
- BPTR lock;
- struct FileInfoBlock *fib;
- struct InfoData *id = NULL;
- int rc = -1;
-
- /* allocate a FileInfoBlock */
- fib = (struct FileInfoBlock *)malloc(sizeof(*fib));
- if (fib == NULL) goto exit;
-
- /* see if the file exists */
- if ((lock = Lock(name, (LONG)ACCESS_READ)) != NULL)
- {
- /* make sure it's not a directory or write protected */
- if (!Examine(lock, fib) ||
- fib->fib_DirEntryType >= 0 ||
- (fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)) )
- goto exit;
- UnLock(lock);
- }
-
- /* strip path from name */
- lastslash = NULL;
- for (p = path; *p = *name; ++p, ++name)
- if (*p == '/' || *p == ':')
- lastslash = p;
-
- /* make sure the path exists */
- if (lastslash)
- {
- lastslash[1] = 0;
- lock = Lock(path, (LONG)ACCESS_READ);
- }
- else
- lock = (CurProc->pr_CurrentDir)
- ? DupLock(CurProc->pr_CurrentDir)
- : NULL;
-
- /* make sure it is a directory that is not write protected */
- if (lock == NULL || !Examine(lock, fib) ||
- fib->fib_DirEntryType <= 0 ||
- (fib->fib_Protection & FIBF_WRITE) )
- goto exit;
-
- /* get device info */
- if ((id = (struct InfoData *)malloc(sizeof(*id))) == NULL) goto exit;
-
- /* make sure the disk is writeable */
- if (Info(lock, id) && id->id_DiskState == ID_VALIDATED)
- rc = 0;
-
- /* clean up */
- exit:
- if (id) free(id);
- if (fib) free(fib);
- if (lock) UnLock(lock);
- return(rc);
- }
-
- /*
- * pipeopen -- execute command to read output like a file
- */
- #define PIPEHOLDER "RAM:Pipe-Holder"
- FILE *pipeopen(command)
- char *command;
- {
- BPTR fh;
-
- /* create holder file */
- fh = Open(PIPEHOLDER, (LONG)MODE_NEWFILE);
- if (fh == NULL) return(0);
-
- /* execute the command */
- Execute(command, (BPTR)NULL, fh);
-
- /* close the holder file */
- Close(fh);
-
- /* reopen it for input */
- return(fopen(PIPEHOLDER, "r"));
- }
-
- /*
- * pipeclose -- clean up after pipe open
- */
- pipeclose(f)
- FILE *f;
- {
- fclose(f);
- DeleteFile(PIPEHOLDER);
- }
-
- /*
- * existobj -- return true if file system object exists
- */
- int existobj(name)
- char *name;
- {
- BPTR lock;
-
- if (*name == 0) return(CurProc->pr_CurrentDir != NULL);
- if ((lock = Lock(name, (LONG)ACCESS_READ)) == NULL)
- return(0);
- UnLock(lock);
- return(1);
- }
-
- /* opendir handle structure */
- struct DirHandle {
- struct FileInfoBlock fib;
- BPTR lock;
- };
-
- /*
- * attempt to open a directory, fill in a handle structure
- */
- struct DirHandle *opendir(name)
- char *name;
- {
- BPTR lock;
- struct DirHandle *dh;
-
- /* get lock on name ("" is current dir) */
- lock = (*name != 0) ? Lock(name, (LONG)ACCESS_READ) :
- (CurProc->pr_CurrentDir) ? DupLock(CurProc->pr_CurrentDir)
- : NULL;
- if (lock == NULL) return(NULL);
- dh = (struct DirHandle *)malloc(sizeof(*dh));
- if (dh == NULL)
- {
- UnLock(lock);
- return(NULL);
- }
- if (!Examine(lock, &dh->fib) || dh->fib.fib_DirEntryType <= 0)
- {
- UnLock(lock);
- free(dh);
- return(NULL);
- }
- /* pass it into the caller's care */
- dh->lock = lock;
- return(dh);
- }
-
- /*
- * return name for next entry in dir
- */
- char *readdir(dh)
- struct DirHandle *dh;
- {
- return(ExNext(dh->lock, &dh->fib) ? dh->fib.fib_FileName : NULL);
- }
-
- /*
- * finish accessing a directory
- */
- VOID closedir(dh)
- struct DirHandle *dh;
- {
- UnLock(dh->lock);
- free(dh);
- }
-